Older people and those with underlying health conditions are at higher risk of being affected by Covid-19. These groups of people were already at higher risk of being socially isolated. Now they are potentially cut off from many of the usual sources of essential support, and they are less likely to have the skills, confidence and devices to get help online.
Public sector and community groups are working hard to support more vulnerable people in society, and we know they are looking for information on how best to target that work. We are determined to put our knowledge and experience to good use, and to help provide that information.
The map below shows 6,470 GP practices in England for which data was available at the last update (October 2021). It is designed to help identify areas where there are more people who don’t tend to use digital tools and services, including those who are not active online at all. To make the map, we’ve used NHS England data on how many patients are ‘enabled’ to use Patient Online GP services, as well as data about the age profile of practices’ patient lists.
We acknowledge that registration alone does not imply confident use of online services. Equally, where people are not enabled for online GP services, this may not indicate a lack of necessary digital skills or access to devices/connectivity.
The R source code that generates the map is viewable by clicking the “Code” button, below right. All the code for this project can be found in the project repository .
The final data that is used for the GP practices information on the map can be downloaded directly, here .
basemaps::set_defaults(map_service = "carto", map_type = "light", map_res = 1)
essex_boundary <- jogger::geo_get("lad", "Essex", "cty", spatial_ref = 3857, return_style = "minimal") %>%
sf::st_union()
bbox_expanded <- myrmidon::expand_sf_bbox(essex_boundary, c(0, 0, 0, 0.34))
basemap <- basemaps::basemap_stars(bbox_expanded)
bbox_crop <- myrmidon::expand_sf_bbox(essex_boundary, 0.05)
basemap_crop <- basemap %>%
sf::st_crop(bbox_crop)
full_data_under70 <- dplyr::filter(full_data_sf, offline_pat_pct < 70)
full_data_over70 <- dplyr::filter(full_data_sf, offline_pat_pct >= 70)
tm_shape(basemap_crop) +
tm_rgb() +
tm_shape(sf::st_join(ccg_bounds, full_data_sf)) +
tm_borders(col = "#6C7B8B", lwd = 1) +
tm_shape(full_data_under70) +
tm_markers(
col = "older_popn_quintile",
size = "total_patients",
scale = 1.2,
perceptual = TRUE,
shape = 21,
alpha = 0.75,
border.col = "#00c5cd",
border.lwd = 2,
border.alpha = 0.9,
palette = "-viridis",
style = "cat",
legend.size.show = TRUE,
legend.col.show = TRUE,
legend.col.is.portrait = FALSE
) +
tm_shape(full_data_over70) +
tm_markers(
col = "older_popn_quintile",
size = "total_patients",
scale = 1.2,
perceptual = TRUE,
shape = 21,
alpha = 0.75,
border.col = "#ee1289",
border.lwd = 2,
border.alpha = 0.9,
palette = "-viridis",
style = "cat",
legend.size.show = FALSE,
legend.col.show = FALSE
) +
tm_shape(essex_boundary) +
tm_borders("cornflowerblue", lwd = 2) +
tm_layout(
title = "",
legend.outside = TRUE,
legend.outside.position = "bottom",
legend.stack = "horizontal"
)# use accessible palette from RColorBrewer
viridis_palette <- leaflet::colorQuantile(palette = "viridis", domain = full_data_sf$age_score, n = 5, reverse = TRUE)
full_data_under40 <- dplyr::filter(full_data_sf, pct_patients_pomi_enabled < 40)
full_data_over40 <- dplyr::filter(full_data_sf, pct_patients_pomi_enabled >= 40)
less_than_forty <- nrow(full_data_under40)
more_than_forty <- nrow(full_data_over40)
gp_map <- leaflet::leaflet(full_data_sf) %>%
addProviderTiles(providers$CartoDB.Positron, options = tileOptions(minZoom = 6, maxZoom = 14)) %>%
addPolygons(
data = ccg_bounds,
stroke = TRUE,
weight = 1,
opacity = 0.75,
color = "#6C7B8B",
fill = TRUE,
fillOpacity = 0,
group = "CCG boundaries",
label = ~ccg20nm
) %>%
addCircles(
data = full_data_over40,
radius = ~ `^`(total_patients, 0.625),
stroke = TRUE,
color = "#00c5cd",
weight = 3,
opacity = 0.75,
fill = TRUE,
fillColor = ~ viridis_palette(age_score),
fillOpacity = 0.75,
label = ~practice_name,
group = "> 40% 'online' (blue border)",
popup = paste0(
"<table>
<tr><th><h3>",
full_data_over40$practice_name,
"</h3>
</th>
<th style = 'font-weight: 400;'>",
full_data_over40$postcode,
"</th>
</tr>",
"<tr>
<td>Total number of patients:</td>
<td style='text-align: right'><strong>",
comma(full_data_over40$total_patients, accuracy = 1),
"</strong></td>
</tr>",
"<tr>
<td>Number of patients aged 65+:</td>
<td style='text-align: right'><strong>",
comma(full_data_over40$over64_patients, accuracy = 1),
"</strong></td>
</tr>",
"<tr>
<td>% patients enabled for online services:</td>
<td style='text-align: right'><strong>",
full_data_over40$pct_patients_pomi_enabled,
"%</strong></td>
</tr>",
"<tr>
<td>Online transactions in ",
pomi_data_month,
" ",
pomi_data_year,
":</td>
<td style='text-align: right'><strong>",
comma(full_data_over40$pomi_total_usage, accuracy = 1),
"</strong></td>
</tr>
</table>"
)
) %>%
addCircles(
data = full_data_under40,
radius = ~ `^`(total_patients, 0.625),
stroke = TRUE,
color = "#ee1289",
weight = 3,
opacity = 0.75,
fill = TRUE,
fillColor = ~ viridis_palette(age_score),
fillOpacity = 0.75,
label = ~practice_name,
group = "< 40% 'online' (pink border)",
popup = paste0(
"<table>
<tr><th><h3>",
full_data_under40$practice_name,
"</h3></th>
<th style = 'font-weight: 400;'>",
full_data_under40$postcode,
"</th>
</tr>",
"<tr>
<td>Total number of patients:</td>
<td style='text-align: right'><strong>",
comma(full_data_under40$total_patients, accuracy = 1),
"</strong></td>
</tr>",
"<tr>
<td>Number of patients aged 65+:</td>
<td style='text-align: right'><strong>",
comma(full_data_under40$over64_patients, accuracy = 1),
"</strong>
</td>
</tr>",
"<tr>
<td>% patients enabled for online services:</td>
<td style='text-align: right'><strong>",
full_data_under40$pct_patients_pomi_enabled,
"%</strong></td>
</tr>",
"<tr>
<td>Online transactions in ",
pomi_data_month,
" ",
pomi_data_year,
":</td>
<td style='text-align: right'><strong>",
comma(full_data_under40$pomi_total_usage, accuracy = 1),
"</strong></td>
</tr>
</table>"
)
) %>%
addLayersControl(
overlayGroups = c(
"< 40% 'online' (pink border)",
"> 40% 'online' (blue border)",
"CCG boundaries"
),
position = "topleft",
options = leaflet::layersControlOptions(collapsed = FALSE)
) %>%
# hideGroup("> 30% 'online' (blue border)") %>%
addLegend(
position = "topright",
colors = viridisLite::viridis(5, direction = -1, alpha = NULL),
opacity = 0.75,
title = "Circle fill colour: proportion of patients<br />aged 65+ (quintiles: 5 = most)",
labels = as.character(1:5)
) %>%
leaflet.extras::addFullscreenControl(
position = "topleft",
pseudoFullscreen = FALSE
) %>%
leaflet::addMiniMap(
tiles = providers$CartoDB.Positron,
zoomLevelOffset = -4,
toggleDisplay = TRUE
)
htmlwidgets::saveWidget(gp_map, "leaflet_widget1.html")
gp_map